{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 第5章 函数 复习\n",
    "* 函数是对象\n",
    "* 函数的参数\n",
    "* 嵌套函数\n",
    "* 特殊函数\n",
    "* 变量作用域"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1、 函数是对象"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<function __main__.bar>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def bar(): \n",
    "    pass   # 占位\n",
    "bar"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1900543982856"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "id(bar)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def foo():\n",
    "    \"\"\"This is a simple function.\"\"\"\n",
    "    return 3.14\n",
    "# dir(foo)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['__annotations__',\n",
       " '__call__',\n",
       " '__class__',\n",
       " '__closure__',\n",
       " '__code__',\n",
       " '__defaults__',\n",
       " '__delattr__',\n",
       " '__dict__',\n",
       " '__dir__',\n",
       " '__doc__',\n",
       " '__eq__',\n",
       " '__format__',\n",
       " '__ge__',\n",
       " '__get__',\n",
       " '__getattribute__',\n",
       " '__globals__',\n",
       " '__gt__',\n",
       " '__hash__',\n",
       " '__init__',\n",
       " '__init_subclass__',\n",
       " '__kwdefaults__',\n",
       " '__le__',\n",
       " '__lt__',\n",
       " '__module__',\n",
       " '__name__',\n",
       " '__ne__',\n",
       " '__new__',\n",
       " '__qualname__',\n",
       " '__reduce__',\n",
       " '__reduce_ex__',\n",
       " '__repr__',\n",
       " '__setattr__',\n",
       " '__sizeof__',\n",
       " '__str__',\n",
       " '__subclasshook__',\n",
       " 'lang']"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "foo.lang = \"python\"\n",
    "dir(foo)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "'function' object has no attribute 'lang'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-12-e4afffbd3746>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mfoo\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlang\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m: 'function' object has no attribute 'lang'"
     ]
    }
   ],
   "source": [
    "foo.lang"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "del foo.lang"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'foo'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "foo.__name__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "from foo\n",
      "1900544758784\n",
      "<class 'function'>\n",
      "<function foo at 0x000001BA814B9400>\n"
     ]
    }
   ],
   "source": [
    "def foo():\n",
    "    print('from foo')\n",
    "foo()\n",
    "\n",
    "print(id(foo))\n",
    "print(type(foo))\n",
    "print(foo)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 函数返回值\n",
    "* 关键词return\n",
    "* 如果没有return语句，默认是return None\n",
    "* 可以返回多个值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n"
     ]
    }
   ],
   "source": [
    "def add(x,y):\n",
    "    r = x+y\n",
    "    return r\n",
    "\n",
    "a = add(3,4)\n",
    "\n",
    "print(a)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1, 2, 3)\n",
      "1 2\n"
     ]
    }
   ],
   "source": [
    "def f():\n",
    "    return 1,2,3\n",
    "\n",
    "r = f()\n",
    "print(r)\n",
    "\n",
    "x,y ,z= f()\n",
    "\n",
    "print(x,y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "def f():\n",
    "    pass\n",
    "f()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2、 参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 必要参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "polynomial() missing 1 required positional argument: 'z'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-24-10dc2df4e790>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      5\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      6\u001b[0m \u001b[1;31m#关键词\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 7\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mpolynomial\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m: polynomial() missing 1 required positional argument: 'z'"
     ]
    }
   ],
   "source": [
    "#多项式s = 1 + 2*x + y^2 + z*y\n",
    "def polynomial(x, y, z):\n",
    "    s = 1 + 2*x + y*y + z*y\n",
    "    return s\n",
    "\n",
    "#关键词\n",
    "print(polynomial(2,3))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 默认参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "15\n"
     ]
    }
   ],
   "source": [
    "def polynomial(x,y,z=3):\n",
    "    s = 1 + 2*x + y*y + z*y\n",
    "    return s\n",
    "\n",
    "#调用函数\n",
    "print(polynomial(x=1,y=2,z=4))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 不定长参数 \n",
    "有两种不定长参数收集方法\n",
    "+  *args --- 用元组收集传入的多个参数，元组给args\n",
    "+  **kwargs  --用字典收集传入特定关键词参数，字典给kwargs\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "(2, 3, 4)\n",
      "{'a': 'python', 'b': 'hello'}\n"
     ]
    }
   ],
   "source": [
    "def print_keywords(x,*args,**kwargs):    \n",
    "    print(x)\n",
    "    print(args)\n",
    "    print(kwargs)\n",
    "\n",
    "print_keywords(1,2,3,4,a='python',b='hello')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3、 嵌套函数  -- 函数是对象，可以作为参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 嵌套函数  -- 向函数中“传函数对象”\n",
    "\n",
    "def foo():\n",
    "    def bar2():\n",
    "        print(\"I am in bar.\")\n",
    "    print(\"I am in foo.\")\n",
    "    return bar2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bar = foo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bar()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def weight(g):\n",
    "    def cal_mg(m):\n",
    "        return m * g\n",
    "    return cal_mg"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "f = weight(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "f(6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get(x):\n",
    "    def clean(t):   #嵌套在get函数内的clean函数\n",
    "        a = t*2 \n",
    "        return a \n",
    "    new_x = clean(x)  #在get函数内调用clean函数\n",
    "    return new_x\n",
    "\n",
    "print(get(5))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4、 特殊函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 装饰器函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def book(name):\n",
    "    return \"My name is {0}\".format(name)\n",
    "def p_dec(func):\n",
    "    def wrapper(name):\n",
    "        return \"<p>{0}</p>\".format(func(name))\n",
    "    return wrapper\n",
    "my = p_dec(book)\n",
    "r = my('laoqi')\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def p_dec(func):\n",
    "    def wrapper(name):\n",
    "        return \"<p>{0}</p>\".format(func(name))\n",
    "    return wrapper\n",
    "@p_dec\n",
    "def book(name):\n",
    "    return \"My name is {0}\".format(name)\n",
    "r2 = book(\"python\")\n",
    "print(r2)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### lambda\n",
    "* for 循环是可以依次得到序列循环中每个元素，并依次处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "lam = lambda x : x + 3\n",
    "lam(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "[(lambda x: x+3)(i) for i in range(10)]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### map\n",
    "* Python 内置的高阶函数，它接收一个函数和一个列表，并通过把函数依次作用在列表的每个元素上，得到一个新的列表并返回\t \n",
    "* 不改变原有的列表，而是返回一个新的列表\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "m = map(lambda x: x+3, range(10))\n",
    "print(list(m))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "n = range(0, 20, 2)\n",
    "r = map(lambda x: x**2, n)\n",
    "print(list(r))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "[i ** 2 for i in n]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "polynomial = lambda x,y,z:1 + 2*x + y*y + z*y\n",
    "print(polynomial(1,2,3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def f(x):#将序列中各元素平方\n",
    "    return x*x\n",
    "print (list(map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#将首字母大写\n",
    "def format_name(s):\n",
    "    s1=s[0:1].upper()+s[1:].lower();\n",
    "    return s1;\n",
    "print(list(map(format_name, ['adam', 'LISA', 'barT']))) \n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### filter\n",
    "* 接收一个函数和一个序列\n",
    "* 把传入的函数依次作用于每个元素，然后根据返回值是True还是False决定保留还是丢弃该元素\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "numbers = range(-5, 5)\n",
    "f = filter(lambda x:x>0, numbers)\n",
    "print(list(f))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "[i for i in numbers if i>0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#删掉偶数，只保留奇数\n",
    "def is_odd(n):\n",
    "    return n % 2 == 1\n",
    "\n",
    "a = filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])\n",
    "print(list(a))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5、 变量作用域"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def echo(p):\n",
    "    L = \"hello\"+p # 定义局部变量L\n",
    "    print(L)\n",
    "echo(\"world\")\n",
    "print(L) #尝试输出局部变量L\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "length = 100# 全局变量\n",
    "def mean(x):\n",
    "    sum_x = 0\n",
    "    for i in x:\n",
    "        sum_x += i\n",
    "    return sum_x/length\n",
    "print(mean(range(101)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 求1到100累加的平均数\n",
    "length = 1\n",
    "def mean(x):\n",
    "    length = 100# 局部变量\n",
    "    sum_x = 0\n",
    "    for i in x:\n",
    "        sum_x += i\n",
    "    return sum_x/length\n",
    "print(mean(range(101)))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
